unit ConnectionDM;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, DB, FileUtil, ZConnection, ZDataset, Dialogs,
  QueryConditions;

{Usuário e senha para conexão com o banco de dados}
const
  CONF_DB_USER = 'user';
  CONF_DB_PASSWORD = 'password';
  CONF_DB_SERVER = 'server';
  CONF_DB_NAME = 'databasename';
  DEFAULT_DB_USER = 'postgres';
  DEFAULT_DB_PASSWORD = 'postgres';
  DEFAULT_DB_SERVER = 'localhost';
  DEFAULT_DB_NAME = 'scats';

type

  { TConnectionData }

  TConnectionData = class(TDataModule)
    PrincipalDataSource: TDatasource;
    PrincipalZConnection: TZConnection;
    PrincipalZQuery: TZQuery;
    procedure OpenQueryConditions(ZQ: TZQuery; TableName: string; QueryConditions: TQueryConditions);
    procedure EmptyQuery(ZQ: TZQuery; Tabela: string);
    procedure DataModuleCreate(Sender: TObject);
    procedure Connect();
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  ConnectionData: TConnectionData;

implementation

uses
  // Unit necessária para criação do arquivo de configuração
  IniFiles, LCLIntf;

{$R *.lfm}

{ TConnectionData }
{procedimento de consultar no banco com as condições estabelecidas, passado
como parâmetro ZQ, tabela, e as condiçẽos pré-estabelecidas pelo usuário}
procedure TConnectionData.OpenQueryConditions(ZQ: TZQuery; TableName: string; QueryConditions: TQueryConditions);
begin
  // Fecha o Dataset
  ZQ.Close();
  // Limpa a consulta do dataset
  ZQ.SQL.Clear();
  // Cria uma nova consulta de acordo com o nome da tabela
  ZQ.SQL.Add('SELECT * FROM ' + TableName);
  // Testa se há condições a serem consideradas
  if (QueryConditions <> nil) and (QueryConditions.GetCount() > 0) then begin
    // Acrescena as condições às condições
    ZQ.SQL.Add('WHERE' + QueryConditions.GetWhereConditions());
  end;
  ZQ.Open();
end;

{Consulta inicial para abrir o ZQ desejado com a consulta específica de uma
tabela retornando LIMIT 0 para menor consumo de mémório}
procedure TConnectionData.EmptyQuery(ZQ: TZQuery; Tabela: string);
begin
  // Fecha o Dataset
  ZQ.Close();
  // Limpa a consulta do dataset
  ZQ.SQL.Clear();
  // Acrescenta uma consulta que não retorna dados apenas para abrir o dataset
  ZQ.SQL.Add('SELECT * FROM ' + Tabela);
  ZQ.SQL.Add('LIMIT 0');
  ZQ.Open();
end;

{Criação do Módulo de Dados}
procedure TConnectionData.DataModuleCreate(Sender: TObject);
var
  Arq: TIniFile;
begin
  {Verifica se já existe o arquivo de configuração}
  if not FileExists(GetAppConfigFile(False)) then begin
    // Se não existir cria o arquivo com as configurações padrões
    if not DirectoryExists(GetAppConfigDir(False)) then begin
      CreateDir(GetAppConfigDir(False));
    end;
    Arq := TIniFile.Create(GetAppConfigFile(False));
    Arq.WriteString('CONFIG', CONF_DB_NAME, DEFAULT_DB_NAME);
    Arq.WriteString('CONFIG', CONF_DB_SERVER, DEFAULT_DB_SERVER);
    Arq.WriteString('CONFIG', CONF_DB_USER, DEFAULT_DB_USER);
    Arq.WriteString('CONFIG', CONF_DB_PASSWORD, DEFAULT_DB_PASSWORD);
    Arq.Free;
  end;
  // Verifica se o programa recebeu algum parâmetro
  if (Paramcount > 0) and (ParamStr(1) = '-config') then begin
    // Abre o arquivo de configuração
    OpenDocument(GetAppConfigFile(False));
  end;
  Connect();
end;

{Função que realiza a conexão com o banco de dados}
procedure TConnectionData.Connect();
var
  Arq: TIniFile;
  Server, DatabaseName, User, Password: string;
begin
  // Abre o arquivo de configuração
  Arq := TIniFile.Create(GetAppConfigFile(False));
  // Lê as configurações
  User := Arq.ReadString('CONFIG', CONF_DB_USER, DEFAULT_DB_USER);
  PrincipalZConnection.User := User;
  Password := Arq.ReadString('CONFIG', CONF_DB_PASSWORD, DEFAULT_DB_PASSWORD);
  PrincipalZConnection.Password := Password;
  Server := Arq.ReadString('CONFIG', CONF_DB_SERVER, DEFAULT_DB_SERVER);
  PrincipalZConnection.HostName := Server;
  DatabaseName := Arq.ReadString('CONFIG', CONF_DB_NAME, DEFAULT_DB_NAME);
  PrincipalZConnection.Database := DatabaseName;
  // Conecta com o banco de dados
  PrincipalZConnection.Connect();

end;

//! Talvez criar um método para gravar em campos readonly, assim não é preciso preocupar nas interfaces

end.
